package com.zz.hhbl.ui

import android.content.Context
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.alibaba.idst.nui.FileUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.ketch.DownloadConfig
import com.ketch.Ketch
import com.ketch.NotificationConfig
import com.ketch.Status
import com.zz.framework.core.ext.printJson
import com.zz.framework.core.ext.toJson
import com.zz.framework.core.http.NetStatusUtils
import com.zz.framework.core.http.XBaseViewModel
import com.zz.framework.core.toast.ToastUtils
import com.zz.framework.core.utils.AppGlobals
import com.zz.framework.core.utils.DeviceUtils
import com.zz.framework.core.utils.EncryptUtils
import com.zz.framework.core.utils.LogUtils
import com.zz.hhbl.App
import com.zz.hhbl.R
import com.zz.hhbl.config.GlobalCache
import com.zz.hhbl.entity.ChatTokenConfigEntity
import com.zz.hhbl.entity.ConfigTempEntity
import com.zz.hhbl.entity.DigitalHumanEntity
import com.zz.hhbl.entity.FenceEntity
import com.zz.hhbl.entity.SpotInfoEntity
import com.zz.hhbl.entity.SpotPointEntity
import com.zz.hhbl.entity.TourGuideCommentaryEntity
import com.zz.hhbl.entity.TranslateEntity
import com.zz.hhbl.entity.VersionEntity
import com.zz.hhbl.entity.VersionType
import com.zz.hhbl.model.CommonHttpRepository
import com.zz.hhbl.utils.LocalUrlUtils
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import retrofit2.http.Body
import retrofit2.http.QueryMap
import java.io.File
import javax.inject.Inject

/**
 * Copyright © 2025 zhun All rights reserved.
 * Created by ZhaoZhun on 2025/2/17 22:09.
 * @author: ZhaoZhun 1820022519@qq.com
 * @version: V1.0
 */
@HiltViewModel
internal class CommonViewModel @Inject constructor(private var repository: CommonHttpRepository) : XBaseViewModel() {
    var ketch: Ketch? = null
    fun initKetch() {
        ketch = Ketch.builder()
            .setDownloadConfig(DownloadConfig())
            .setNotificationConfig(NotificationConfig(true, smallIcon = R.mipmap.ic_logo))
            .enableLogs(true)
            .build(AppGlobals.getApplication())
    }

    val loginState = MutableLiveData<String?>()
    fun login() {
        val code = DeviceUtils.getSerialCode()
        val secret = "Lhhwl2025@device"
        val password = EncryptUtils.encryptHmacMD5ToString(code, secret)
        quickLaunch {
            repository.login(
                hashMapOf(
                    "username" to code,
                    "password" to password
                )
            ).onSuccess {
                GlobalCache.setToken(it)
                loginState.postValue(it)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    private val _versionState = MutableLiveData<List<VersionEntity>?>()
    val versionState: LiveData<List<VersionEntity>?> get() = _versionState
    fun getVersion() {
        quickLaunch {
            repository.getVersion(hashMapOf()).onSuccess {
                it?.data?.filter { it.version.isNullOrEmpty().not() }?.forEach {
                    when (it.type) {
                        //app版本
                        VersionType.APP.type -> GlobalCache.setAppVersion(it.version!!)
                        //景点信息
                        VersionType.SPOT.type -> GlobalCache.setSpotVersion(it.version!!)
                        VersionType.TOUR_GUIDE_COMMENTARY.type -> GlobalCache.setTourGuideCommentaryVersion(it.version!!)
                        VersionType.DIGITAL_HUMAN.type -> GlobalCache.setDigitalHumanVersion(it.version!!)
                        VersionType.ELECTRONIC_FENCE.type -> GlobalCache.setElectronicFenceVersion(it.version!!)
                    }
                }
                it?.langlist?.let {
                    GlobalCache.setLanguageList(it)
                }
                _versionState.postValue(it?.data)
            }.onFailure {
                onError(it.toJson())
            }
        }
    }


    private val _spotInfoState = MutableLiveData<SpotInfoEntity?>()
    val spotInfoState: LiveData<SpotInfoEntity?> get() = _spotInfoState
    fun getSpotInfo() {
        quickLaunch {
            repository.getSpotInfo(hashMapOf()).onSuccess {
                GlobalCache.setSpotInfo(it)
                cacheSpotInfo(it)
                _spotInfoState.postValue(it)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    private val _allCacheMapState = MutableLiveData<Map<String, ConfigTempEntity>?>()
    val allCacheMapState: LiveData<Map<String, ConfigTempEntity>?> get() = _allCacheMapState
    fun getAllData() {
        quickLaunch {
            repository.getAllData(hashMapOf()).onSuccess {
                it?.forEach { language, entity ->
                    run {
                        //获取景点欢迎页面
                        GlobalCache.setSpotInfo(entity.spotInfo, language = language)
                        //数字人
                        GlobalCache.setDigitalHuman(entity.digitalHumans, language = language)
                        GlobalCache.setFence(entity.fences, language = language)
                        GlobalCache.setTourGuideCommentary(entity.tourGuideCommentary, language = language)
                        //景点欢迎页面
                        cacheSpotInfo(entity.spotInfo)
                        //数字人
                        cacheDigitalHumans(entity.digitalHumans)
                        //景点讲解词
                        cacheTourGuideCommentary(entity.tourGuideCommentary)
                    }
                }
                _allCacheMapState.postValue(it)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    private fun cacheDigitalHumans(digitalHumans: List<DigitalHumanEntity>?) {
        digitalHumans?.forEach {
            it.aiAvatarImgListening?.filter { it.type?.contains("image") == true }?.forEach {
                GlobalCache.precacheImage(it.url)
            }
            it.aiAvatarImgSpeaking?.filter { it.type?.contains("image") == true }?.forEach {
                GlobalCache.precacheImage(it.url)
            }
            it.background?.filter { it.type?.contains("image") == true }?.forEach {
                GlobalCache.precacheImage(it.url)
            }
            it.aiAvatarImgStop?.filter { it.type?.contains("image") == true }?.forEach {
                GlobalCache.precacheImage(it.url)
            }
        }
    }

    private fun cacheTourGuideCommentary(list: List<TourGuideCommentaryEntity>?) {
        list?.forEach {
            GlobalCache.precacheImage(it.exampleImage)
        }
    }

    private fun cacheSpotInfo(entity: SpotInfoEntity?) {
        entity?.let {
            it.welcomeData?.filter { it.type?.contains("image") == true }?.forEach {
                GlobalCache.precacheImage(it.url)
            }
            it.bootPageData?.filter { it.type?.contains("image") == true }?.forEach {
                GlobalCache.precacheImage(it.url)
            }
        }
    }

    private val _tourGuideCommentaryState = MutableLiveData<List<TourGuideCommentaryEntity>?>()
    val tourGuideCommentaryState: LiveData<List<TourGuideCommentaryEntity>?> get() = _tourGuideCommentaryState
    fun getTourGuideCommentary() {
        quickLaunch {
            repository.getTourGuideCommentary(hashMapOf()).onSuccess {
                _tourGuideCommentaryState.postValue(it)
                cacheTourGuideCommentary(it)
                GlobalCache.setTourGuideCommentary(it)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    private val _fenceState = MutableLiveData<List<FenceEntity>?>()
    val fenceState: LiveData<List<FenceEntity>?> get() = _fenceState
    fun fence() {
        quickLaunch {
            repository.fence(hashMapOf()).onSuccess {
                GlobalCache.setFence(it)
                _fenceState.postValue(it)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    private val _digitalHumanState = MutableLiveData<List<DigitalHumanEntity>?>()
    val digitalHumanState: LiveData<List<DigitalHumanEntity>?> get() = _digitalHumanState
    fun digitalHuman() {
        quickLaunch {
            repository.digitalHuman(hashMapOf()).onSuccess {
                GlobalCache.setDigitalHuman(it)
                cacheDigitalHumans(it)
                _digitalHumanState.postValue(it)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    private val _syncDeviceStatusState = MutableLiveData<Boolean>()
    val syncDeviceStatusState: LiveData<Boolean> get() = _syncDeviceStatusState
    fun syncDeviceStatus() {
        quickLaunch {
            repository.syncDeviceStatus(hashMapOf()).onSuccess {
                _syncDeviceStatusState.postValue(true)
            }.onFailure {
                _syncDeviceStatusState.postValue(false)
                onError(it.message.orEmpty())
            }
        }
    }

    private val _fenceWarningState = MutableLiveData<Boolean>()
    val fenceWarningState: LiveData<Boolean> get() = _fenceWarningState
    fun fenceWarning(params: HashMap<String, Any?>) {
        quickLaunch {
            repository.fenceWarning(params).onSuccess {
                _fenceWarningState.postValue(true)
            }.onFailure {
                _fenceWarningState.postValue(false)
                onError(it.message.orEmpty())
            }
        }
    }

    var fetchMultipleRequestsState = MutableLiveData<Boolean>(false)
    fun fetchMultipleRequests() {
        zipLaunch(
            { repository.getTourGuideCommentary(hashMapOf()) },
            { repository.getSpotInfo(hashMapOf()) },
            { repository.fence(hashMapOf()) },
            { repository.digitalHuman(hashMapOf()) }
        ) { results ->
            run {
                val result1 = results[0] as? Result<List<TourGuideCommentaryEntity>?>
                val result2 = results[1] as? Result<SpotInfoEntity?>
                val result3 = results[2] as? Result<List<FenceEntity>?>
                val result4 = results[3] as? Result<List<DigitalHumanEntity>?>
                result1?.onSuccess {
                    _tourGuideCommentaryState.value = it
                    GlobalCache.setTourGuideCommentary(it)
                }?.onFailure {
                    onError(it.message.orEmpty())
                }
                result2?.onSuccess {
                    _spotInfoState.value = it
                    GlobalCache.setSpotInfo(it)
                    it?.welcomeData?.filter { it.type == "image" }?.forEach {
                        GlobalCache.precacheImage(it.url)
                    }
                    it?.bootPageData?.filter { it.type == "image" }?.forEach {
                        GlobalCache.precacheImage(it.url)
                    }
                }?.onFailure {
                    onError(it.message.orEmpty())
                }
                result3?.onSuccess {
                    _fenceState.value = it
                    GlobalCache.setFence(it)
                }?.onFailure {
                    onError(it.message.orEmpty())
                }
                result4?.onSuccess {
                    _digitalHumanState.value = it
                    GlobalCache.setDigitalHuman(it)
                    it?.forEach {
                        it.aiAvatarImgListening?.forEach {
                            GlobalCache.precacheImage(it.url)
                        }
                        it.aiAvatarImgSpeaking?.forEach {
                            GlobalCache.precacheImage(it.url)
                        }
                        it.background?.forEach {
                            GlobalCache.precacheImage(it.url)
                        }
                        it.aiAvatarImgStop?.forEach {
                            GlobalCache.precacheImage(it.url)
                        }

                    }
                }?.onFailure {
                    onError(it.message.orEmpty())
                }
                fetchMultipleRequestsState.postValue(true)
            }
        }
    }


    private val _getChatTokenConfigLiveData = MutableLiveData<ChatTokenConfigEntity>()
    val getChatTokenConfigLiveData: LiveData<ChatTokenConfigEntity> get() = _getChatTokenConfigLiveData
    fun getChatTokenConfig() {
        quickLaunch {
            repository.getChatTokenConfig(deviceNumber = DeviceUtils.getSerialCode()).onSuccess {
                GlobalCache.setAiConfig(it)
                _getChatTokenConfigLiveData.postValue(it)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    private val _startVoiceChatLiveData = MutableLiveData<ChatTokenConfigEntity>()
    val startVoiceChatLiveData: LiveData<ChatTokenConfigEntity> get() = _startVoiceChatLiveData
    fun startVoiceChat(params: HashMap<String, Any?>) {
        //voiceType: String? = "BV005_streaming"
        params.put("deviceNumber", DeviceUtils.getSerialCode())
        quickLaunch {
            repository.startVoiceChat(params).onSuccess {
                _startVoiceChatLiveData.postValue(it)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    private val _spotPointMarksLiveData = MutableLiveData<List<SpotPointEntity>>()
    val spotPointMarksLiveData: LiveData<List<SpotPointEntity>> get() = _spotPointMarksLiveData
    fun getMapSpotPointMarks() {
        quickLaunch {
            repository.getMapSpotPointMarks().onSuccess {
                _spotPointMarksLiveData.postValue(it)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }


    private val _stopVoiceChatLiveData = MutableLiveData<Boolean>()
    val stopVoiceChatLiveData: LiveData<Boolean> get() = _stopVoiceChatLiveData
    fun stopVoiceChat(deviceNumber: String? = DeviceUtils.getSerialCode()) {
        quickLaunch {
            repository.stopVoiceChat(deviceNumber).onSuccess {
                _stopVoiceChatLiveData.postValue(true)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    fun recordSosInfo(longitude: Double, latitude: Double) {
        quickLaunch {
            repository.recordSosInfo(hashMapOf("longitude" to longitude, "latitude" to latitude)).onSuccess {}.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    private val _stopVoiceChatLiveData2 = MutableLiveData<Boolean>()
    val stopVoiceChatLiveData2: LiveData<Boolean> get() = _stopVoiceChatLiveData2
    fun stopVoiceChat2(deviceNumber: String? = DeviceUtils.getSerialCode()) {
        quickLaunch {
            repository.stopVoiceChat(deviceNumber).onSuccess {
                _stopVoiceChatLiveData2.postValue(true)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }

    private val _updateVoiceChatLiveData = MutableLiveData<Boolean>()
    val updateVoiceChatLiveData: LiveData<Boolean> get() = _updateVoiceChatLiveData
    fun updateVoiceChat(params: HashMap<String, Any?>) {
        quickLaunch {
            repository.updateVoiceChat(params).onSuccess {
                _updateVoiceChatLiveData.postValue(true)
            }.onFailure {
                onError(it.message.orEmpty())
            }
        }
    }


    fun download(urls: List<String>) {
        urls.forEach {
            download(it)
        }
    }


    private fun download(url: String, isApk: Boolean = false) {
        if (LocalUrlUtils.isLocalExists(url)) {
            if (url.endsWith(".apk") == true) {
                _downloadApkSuccessLiveData.postValue(LocalUrlUtils.getLocalPathByUrl(url))
            }
            return
        }
//        if (isApk && LocalUrlUtils.isLocalExists(url)) {
//            FileUtil.deleteFile(LocalUrlUtils.getLocalPathByUrl(url))
//        }
        viewModelScope.launch() {
            ketch?.let { ketch ->
                val taskId = ketch.download(url = url, fileName = LocalUrlUtils.getFileNameByUrl(url), path = LocalUrlUtils.getLocalFolderPath())
                ketch.observeDownloadById(taskId)
                    .flowOn(Dispatchers.IO)
                    .collect { item ->
                        item.printJson()
                        when (item.status) {
                            Status.SUCCESS -> {
                                if (item.fileName?.endsWith(".apk") == true) {
                                    _downloadApkSuccessLiveData.postValue(item.path + "/" + item.fileName)
                                }
                            }

                            Status.FAILED, Status.PAUSED, Status.CANCELLED -> {
                                LogUtils.error("${item.url} ==> failureReason:${item.failureReason}")
                                ketch.retry(taskId)
                                if (item.fileName?.endsWith(".apk") == true) {
                                    _downloadApkFailureLiveData.postValue(false)
                                }
                            }

                            Status.PROGRESS, Status.QUEUED, Status.STARTED -> {
                                LogUtils.error("${item.url} ==> progress:${item.progress}")
                            }

                            else -> {
                                LogUtils.error("${item.url} ==> failureReason:${item.failureReason}")
                                ketch.retry(taskId)
                                if (item.fileName?.endsWith(".apk") == true) {
                                    _downloadApkFailureLiveData.postValue(false)
                                }
                            }
                        }
                    }
            }
        }
    }


    private val _downloadApkSuccessLiveData = MutableLiveData<String>()
    val downloadApkSuccessLiveData: LiveData<String> get() = _downloadApkSuccessLiveData
    private val _downloadApkFailureLiveData = MutableLiveData<Boolean>()
    val downloadApkFailureLiveData: LiveData<Boolean> get() = _downloadApkFailureLiveData
    fun downloadApk(url: String) {
        download(url, true)
    }


    private val _audioCreateLiveData = MutableLiveData<TranslateEntity>()
    val audioCreateLiveData: LiveData<TranslateEntity> get() = _audioCreateLiveData
    fun audioCreate(sourceLanguage: String, targetLanguage: String, fileUrl: String) {
        val file = File(fileUrl)
        val filePart = MultipartBody.Part.createFormData("AudioFile", file.name, file.asRequestBody())
        val sourceLang = RequestBody.create("text/plain".toMediaTypeOrNull(), sourceLanguage)
        val targetLang = RequestBody.create("text/plain".toMediaTypeOrNull(), targetLanguage)
        quickLaunch {
            repository.audioCreate(sourceLang, targetLang, filePart).onSuccess {
                if (it?.code == 0 || it?.code == 10) {
                    it?.taskId?.let {
                        _audioCreateLiveData.postValue(
                            TranslateEntity(
                                taskId = it,
                                isUserVoice = false,
                                status = 0,
                                text = "$it 的翻译",
                                url = ""
                            )
                        )
                    }
                } else {
                    ToastUtils.show(it?.message ?: "请求失败")
                }
            }.onFailure {
                ToastUtils.show("请求失败")
            }
        }
    }

    fun audioGetResult(params: HashMap<String, Any?>) {
        quickLaunch {
            repository.audioGetResult(params)
        }
    }


    private val _audioGetStatusLiveData = MutableLiveData<TranslateEntity>()
    val audioGetStatusLiveData: LiveData<TranslateEntity> get() = _audioGetStatusLiveData
    fun audioGetStatus(item: TranslateEntity) {
        quickLaunch {
            repository.audioGetStatus(hashMapOf("task_id" to item.taskId)).onSuccess {
                if (it?.code == 0 || it?.code == 10) {
                    _audioGetStatusLiveData.postValue(item.also {
                        it.status = 1
                        it.url = "http://222.212.90.223:42059/api/Audio/GetResult?task_id=${item.taskId}"
                    })
                } else  {
                    _audioGetStatusLiveData.postValue(item.also { entity->
                        if (it?.code == 10001){
                            entity.status = 0
                        }else {
                            entity.status = 2
                        }
                    })
                    if (it?.code != 10001) {
                        ToastUtils.show(it?.message ?: "请求失败")
                    }
                }
            }.onFailure {
                _audioGetStatusLiveData.postValue(item.also {
                    it.status = 2
                })
                ToastUtils.show("请求失败")
            }
        }
    }
}

